<?php

namespace app\common\listener;

use app\common\model\Company;
use app\common\model\DealerGoods;
use app\common\model\DealerGoodsSpec;
use app\company\model\CompanyOrder;
use app\company\model\CompanyPickOrder;
use app\company\model\CompanyTransferOrderDetail;
use app\company\model\DealerOrder;
use think\Container;
use think\facade\Db;
use think\facade\Log;
use think\swoole\Websocket;
use Swoole\Timer;

class GroupScreen
{
    protected object $websocket;
    protected array  $tickId;

    public function __construct(Container $container)
    {
        $this->websocket = $container->make(Websocket::class);
    }

    /**
     * 事件监听处理
     */
    public function handle($event): void
    {
        // 公司数据
        $this->getCompany();
        // 仓库数据
        $this->getWarehouse();
        // 公司经营数据
        $this->getCompanyData();
        // 公司订单量数据
        $this->getCompanyOrder();
        // 公司一周数据情况
        $this->getCompanyWeekData();
        // 获取当前最新订单数据
        $this->getNewOrder();
        // 仓内货值金额
        $this->getWarehouseAmount();
    }

    private function getCompany(): void
    {
        $data = (new Company())->where('status', 1)->field('id,name,short_name,lng,lat')
                               ->select()->each(function ($item)
                {
                    $item->dealer_num    = Db::name('dealer')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    // 本月新增经销商数量
                    $item->dealer_month_add_num = Db::name('dealer')
                                                 ->where('company_id', $item->id)
                                                 ->where('status', 1)
                                                 ->whereTime('create_time', 'month')
                                                 ->where('delete_time',null)
                                                 ->count() ?? 0;
                    $item->store_num     = Db::name('store')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    $item->store_month_add_num = Db::name('store')
                                                 ->where('company_id', $item->id)
                                                 ->where('status', 1)
                                                 ->whereTime('create_time', 'month')
                                                 ->where('delete_time',null)
                                                 ->count() ?? 0;
                    $item->salesman_num  = Db::name('salesman')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    $item->salesman_month_add_num = Db::name('salesman')
                                                 ->where('company_id', $item->id)
                                                 ->where('status', 1)
                                                 ->whereTime('create_time', 'month')
                                                 ->where('delete_time',null)
                                                 ->count() ?? 0;
                    $item->driver_num    = Db::name('driver')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    $item->driver_month_add_num = Db::name('driver')
                                                 ->where('company_id', $item->id)
                                                 ->where('status', 1)
                                                 ->whereTime('create_time', 'month')
                                                 ->where('delete_time',null)
                                                 ->count() ?? 0;
                    $item->warehouse_num = Db::name('company_warehouse')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    $item->supplier_num = Db::name('supplier')
                                             ->where('company_id', $item->id)
                                             ->where('status', 1)
                                             ->where('delete_time',null)
                                             ->count() ?? 0;
                    $item->supplier_month_add_num = Db::name('supplier')
                                                 ->where('company_id', $item->id)
                                                 ->where('status', 1)
                                                 ->whereTime('create_time', 'month')
                                                 ->where('delete_time',null)
                                                 ->count() ?? 0;
                });
        // 推送数据
        $this->websocket->to($this->websocket->getSender())->emit('company', $data);
    }

    // 仓库总金额，
    private function getWarehouse(): void
    {
        // 主仓库数量
        $warehouseNum = Db::name('company_warehouse')
                          ->where('status', 1)
                          ->where('type', 1)
                          ->where('delete_time',null)
                          ->count();
        // 移动仓数量
        $moveWarehouseNum = Db::name('company_warehouse')
                              ->where('status', 1)
                              ->where('type', 2)
                              ->where('delete_time',null)
                              ->count();

        $goods = (new DealerGoods())->where('status', 1)
                                    ->where('warehouse_stock', '>', 0)
                                    ->field('id,warehouse_stock')->select()->each(function ($item)
                {
                    // 货值金额
                    $price        = $item->spec()->where('unit_type', 1)->value('sale_price');
                    $item->amount = $item->warehouse_stock * $price;
                    // 大单位换算比例
                    $b_ratio = $item->spec()->where('unit_type', 2)->value('ratio') ?? 0;
                    // 大单位数量（warehouse_stock / $m_ratio 取整）
                    $item->b_num = $b_ratio ? intval($item->warehouse_stock / $b_ratio) : 0;
                    // 中单位换算比例
                    $m_ratio = $item->spec()->where('unit_type', 3)->value('ratio') ?? 0;
                    // 中单位数量（$item->m_num / $l_ratio 取整）
                    $item->m_num = $m_ratio ? intval($item->warehouse_stock / $m_ratio) : 0;
                })->toArray();

        // 在仓总货值
        $warehouseGoodsAmount = array_sum(array_column($goods, 'amount'));
        // 小单位数量
        $warehouseGoodsMinNum = array_sum(array_column($goods, 'warehouse_stock'));
        // 中单位数量
        $warehouseGoodsMidNum = array_sum(array_column($goods, 'm_num'));
        // 大单位数量
        $warehouseGoodsBigNum = array_sum(array_column($goods, 'b_num'));
        // 出库总数量
        $outNum = (new CompanyPickOrder())->where('pick_order_status', 3)->sum('order_num');
        // 今日出库总数量
        $todayOutNum = (new CompanyPickOrder())->where('pick_order_status', 3)->whereTime('create_time', 'today')
                                               ->sum('order_num');
        // 出库总金额
        $amount      = (new CompanyPickOrder())->where('pick_order_status', 3)
                                               ->field('company_order_ids,dealer_order_ids,transfer_order_ids')
                                               ->select()->each(function ($item)
                {
                    if ($item->company_order_ids) {
                        $item->amount = (new CompanyOrder())->whereIn('id', json_decode($item->company_order_ids, true))
                                                            ->sum('order_amount');
                    } elseif ($item->dealer_order_ids) {
                        $item->amount = (new DealerOrder())->whereIn('id', json_decode($item->dealer_order_ids, true))
                                                           ->sum('order_amount');
                    } elseif ($item->transfer_order_ids) {
                        $amount = 0;
                        (new CompanyTransferOrderDetail())->whereIn('t_oid',
                                                                    json_decode($item->transfer_order_ids, true))
                                                          ->select()->each(function ($item) use (&$amount)
                                {
                                    $price  = (new DealerGoodsSpec())->where('id', $item->dealer_goods_spec_id)
                                                                     ->value('sale_price');
                                    $amount += $item->transfer_num * $price;
                                });
                        $item->amount = $amount;
                    }
                });
        $orderAmount = sprintf("%.2f", array_sum(array_column($amount->toArray(), 'amount')));

        // 今日出库总额
        $toadyAmount      = (new CompanyPickOrder())->where('pick_order_status', 3)->whereTime('create_time', 'today')
                                                    ->field('company_order_ids,dealer_order_ids,transfer_order_ids')
                                                    ->select()->each(function ($item)
                {
                    if ($item->company_order_ids) {
                        $item->amount = (new CompanyOrder())->whereIn('id', json_decode($item->company_order_ids, true))
                                                            ->sum('order_amount');
                    } elseif ($item->dealer_order_ids) {
                        $item->amount = (new DealerOrder())->whereIn('id', json_decode($item->dealer_order_ids, true))
                                                           ->sum('order_amount');
                    } elseif ($item->transfer_order_ids) {
                        $amount = 0;
                        (new CompanyTransferOrderDetail())->whereIn('t_oid',
                                                                    json_decode($item->transfer_order_ids, true))
                                                          ->select()->each(function ($item) use (&$amount)
                                {
                                    $price  = (new DealerGoodsSpec())->where('id', $item->dealer_goods_spec_id)
                                                                     ->value('sale_price');
                                    $amount += $item->transfer_num * $price;
                                });
                        $item->amount = $amount;
                    }
                });
        $todayOrderAmount = sprintf("%.2f", array_sum(array_column($toadyAmount->toArray(), 'amount')));

        // 入库总数量
        $warehouseGoods = (new DealerOrder())->where('order_type', 1)->where('order_status', 3)
                                             ->select()
                                             ->each(function ($item)
                                             {
                                                 $item->real_num = $item->detail()->sum('real_num');
                                             });
        $inWarehouseNum = array_sum(array_column($warehouseGoods->toArray(), 'real_num'));
        // 入库金额
        $inWarehouseGoodsAmount = sprintf("%.2f", array_sum(array_column($warehouseGoods->toArray(), 'order_amount')));
        // 今日入库总数量
        $todayWarehouseGoods = (new DealerOrder())->where('order_type', 1)->where('order_status', 3)
                                                  ->whereTime('create_time', 'today')
                                                  ->select()
                                                  ->each(function ($item)
                                                  {
                                                      $item->real_num = $item->detail()->sum('real_num');
                                                  });
        $todayInWarehouseNum = array_sum(array_column($todayWarehouseGoods->toArray(), 'real_num'));
        // 今日入库金额
        $todayInWarehouseGoodsAmount = sprintf("%.2f", array_sum(array_column($todayWarehouseGoods->toArray(),
                                                                              'order_amount')));
        // 推送数据
        $this->websocket->to($this->websocket->getSender())
                        ->emit('warehouse', compact('warehouseNum', 'moveWarehouseNum',
                                                    'warehouseGoodsAmount', 'warehouseGoodsMinNum',
                                                    'warehouseGoodsMidNum', 'warehouseGoodsBigNum',
                                                    'outNum', 'todayOutNum', 'orderAmount',
                                                    'todayOrderAmount', 'inWarehouseNum', 'inWarehouseGoodsAmount',
                                                    'todayInWarehouseNum', 'todayInWarehouseGoodsAmount'));
    }

    private function getCompanyData(): void
    {
        $companyNum   = Db::name('company')->where('status', 1)->where('delete_time',null)->count();
        $dealerNum    = Db::name('dealer')->where('status', 1)->where('delete_time',null)->count();
        $storeNum     = Db::name('store')->where('status', 1)->where('delete_time',null)->count();
        $salesmanNum  = Db::name('salesman')->where('status', 1)->where('delete_time',null)->count();
        $driverNum    = Db::name('driver')->where('status', 1)->where('delete_time',null)->count();
        $warehouseNum = Db::name('company_warehouse')->where('status', 1)->where('delete_time',null)->count();
        // 推送数据
        $this->websocket->to($this->websocket->getSender())
                        ->emit('company_data', compact('companyNum', 'dealerNum', 'storeNum',
                                                       'salesmanNum', 'driverNum', 'warehouseNum'));
    }

    private function getCompanyOrder(): void
    {
        $data = (new Company())->where('status', 1)->field('id,name,short_name')->select()->each(function ($item)
        {
            $item->order_num          = $item->orders()->where('order_status', '<>', 3)->count();
            $item->order_amount       = sprintf("%.2f",
                                                $item->orders()->where('order_status', '<>', 3)->sum('order_amount'));
            $item->transfer_order_num = Db::name('company_transfer_order')
                                          ->where('company_id', $item->id)
                                          ->where('order_status', '<>', 3)
                                          ->where('delete_time',null)
                                          ->count();
            // 采购单数量
            $item->purchase_order_num    = Db::name('dealer_order')->where('company_id', $item->id)
                                             ->where('order_type', 1)->where('delete_time',null)->count();
            $item->purchase_order_amount = sprintf("%.2f", Db::name('dealer_order')->where('company_id', $item->id)
                                                             ->where('order_type', 1)->where('delete_time',null)->sum('order_amount'));
        })->toArray();
        $this->websocket->to($this->websocket->getSender())->emit('company_order', $data);
    }

    private function getCompanyWeekData(): void
    {
        $count = 6;
        $list = [];
        $nowYear = date('Y');
        $nowMonth = date('m');
        for ($i = 0; $i < $count; $i++) {
//            $time = date('Y-m-d', strtotime('-' . $day . ' days'));
            // 计算当前循环的月份和年份
            $month =  $nowMonth -  $i;
            $year =  $nowYear;
            // 如果月份小于1，则调整年份和月份
            if ($month < 1) {
                $year--;
                $month = 12 +  $month;
            }
            // 将月份补零
            $month = str_pad( $month, 2, '0', STR_PAD_LEFT);
            $date =  $year. '-'. $month;
            $firstDay = date('Y-m-01', strtotime($date));
            $lastDay = date('Y-m-d', strtotime("$firstDay +1 month -1 day"));
            // 查询当前时间开始以及结束时的订单
            $orderNum            = Db::name('company_order')->where('order_status', '<>', 3)
                                     ->where('create_time', 'between', [strtotime($firstDay . ' 00:00:00'), strtotime($lastDay . ' 23:59:59')])
                                     ->where('delete_time',null)
                                     ->count();
            $orderAmount         = sprintf("%.2f", Db::name('company_order')->where('order_status', '<>', 3)
                                                     ->where('create_time', 'between',  [strtotime($firstDay . ' 00:00:00'), strtotime($lastDay . ' 23:59:59')])
                                                     ->where('delete_time',null)
                                                     ->sum('order_amount'));
            $transferOrderNum    = Db::name('company_transfer_order')->where('order_status', '<>', 3)
                                     ->where('create_time', 'between',  [strtotime($firstDay . ' 00:00:00'), strtotime($lastDay . ' 23:59:59')])
                                     ->where('delete_time',null)
                                     ->count();
            $purchaseOrderNum    = Db::name('dealer_order')->where('order_type', 1)
                                     ->where('create_time', 'between',  [strtotime($firstDay . ' 00:00:00'), strtotime($lastDay . ' 23:59:59')])
                                     ->where('delete_time',null)
                                     ->count();
            $purchaseOrderAmount = sprintf("%.2f", Db::name('dealer_order')->where('order_type', 1)
                                                     ->where('create_time', 'between',  [strtotime($firstDay . ' 00:00:00'), strtotime($lastDay . ' 23:59:59')])
                                                     ->where('delete_time',null)
                                                     ->sum('order_amount'));
            $list[]              = [
                    'time'                  => $date,
                    'order_num'             => $orderNum,
                    'order_amount'          => $orderAmount,
                    'transfer_order_num'    => $transferOrderNum,
                    'purchase_order_num'    => $purchaseOrderNum,
                    'purchase_order_amount' => $purchaseOrderAmount,
            ];
        }
        $list = array_reverse($list);
        $this->websocket->to($this->websocket->getSender())->emit('company_order_week', $list);
    }

    /**
     * 查询今日最新公司订单量，订单金额，每分钟轮训查询定时推送
     * @return void
     */
    private function getNewOrder(): void
    {
        // 查询今日最新公司订单量和订单金额
        $data = (new Company())->field('id,name,short_name')->select()->each(function ($item){
            // 今日订单数量
            $item->order_num = (new CompanyOrder())->where('company_id', $item->id)
                                                   ->where('order_status', '<>', 3)
                                                   ->where('create_time', 'between', [date('Y-m-d') . ' 00:00:00', date('Y-m-d') . ' 23:59:59'])
                                                   ->count();
            // 今日订单金额
            $item->order_amount = sprintf("%.2f", (new CompanyOrder())->where('company_id', $item->id)
                                                                      ->where('order_status', '<>', 3)
                                                                      ->where('create_time', 'between', [date('Y-m-d') . ' 00:00:00', date('Y-m-d') . ' 23:59:59'])
                                                                      ->sum('order_amount'));
        })->toArray();
        // 推送数据
        $this->websocket->to($this->websocket->getSender())->emit('company_order_new', $data);

        // 每分钟轮询查询定时推送
        $this->tickId[] = Timer::tick(60000, function () {
            $this->getNewOrder();
        });
    }

    private function getWarehouseAmount(): void
    {
        $data = (new Company())->where('status',1)->field('id,name,short_name')->select()->each(function ($item){

            $goods = (new DealerGoods())->where('status', 1)->where('company_id', $item->id)
                                        ->where('warehouse_stock', '>', 0)
                                        ->field('id,warehouse_stock')->select()->each(function ($item)
                    {
                        // 货值金额
                        $price        = $item->spec()->where('unit_type', 1)->value('sale_price');
                        $item->amount = $item->warehouse_stock * $price;
                    })->toArray();
            $item->goodsAmount = sprintf("%.2f", array_sum(array_column($goods, 'amount')));
        })->toArray();
        $goodsTotalAmount = sprintf("%.2f", array_sum(array_column($data, 'goodsAmount')));
        $this->websocket->to($this->websocket->getSender())->emit('company_goods_amount', ['data' => $data, 'total_amount' => $goodsTotalAmount]);
    }

    // 定时器清理
    public function clearTimers($fd): void
    {
        if (isset($this->tickId[$fd])) {
            Timer::clear($this->tickId[$fd]);
            unset($this->tickId[$fd]);
        }
    }

}